package org.example.pinda.context;

import org.example.pinda.util.NumberHelper;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

/**
 * 基础上下文工具类
 * <p>
 * 获取当前域中的用户ID、用户名等信息
 *
 * @author ryan fawcett
 * @see BaseContextConstants
 */
public class BaseContextHandler {

    private static final String EMPTY = "";

    private static final ThreadLocal<Map<String, String>> CACHE = new ThreadLocal<>();

    /**
     * 获取缓存Map对象，如果获取的结果为空，则重新初始化一个初始容量为10的Map，
     * 并将这个Map赋值给缓存对象，同时将该Map进行返回
     *
     * @return 缓存Map
     */
    public static Map<String, String> getCache() {
        Map<String, String> cache = CACHE.get();
        if (cache == null) {
            cache = new HashMap<>(10);
            CACHE.set(cache);
        }
        return cache;
    }

    /**
     * 获取缓存Map设置键值对，如果存储的值为空，则默认存储空字符串
     *
     * @param key 键
     * @param val 值
     */
    public static void set(String key, String val) {
        getCache().put(key, getValue(val, String::toString, EMPTY));
    }

    /**
     * 获取缓存Map设置键值对
     *
     * @param key        键
     * @param val        值
     * @param defaultVal 默认值
     */
    public static void set(String key, Object val, String defaultVal) {
        getCache().put(key, getValue(val, Object::toString, defaultVal));
    }

    /**
     * 获取缓存Map设置键值对，如果存储的值为空，则默认存储 'false'
     *
     * @param key 键
     * @param val 值
     */
    public static void set(String key, Boolean val) {
        set(key, val, "false");
    }

    /**
     * 获取缓存Map设置键值对，如果存储的值为空，则默认存储 '0'
     *
     * @param key 键
     * @param val 值
     */
    public static void set(String key, Long val) {
        set(key, val, "0L");
    }

    /**
     * 根据键获取值，如果不存在则返回空字符串
     *
     * @param key 键
     * @return 值
     */
    public static String get(String key) {
        return getCache().getOrDefault(key, EMPTY);
    }

    public static <T, R> R getValue(T t, Function<T, R> func, R defaultVal) {
        try {
            return func.apply(t);
        } catch (Exception e) {
            return defaultVal;
        }
    }

    public static String getDefaultVal(String oldVal, String defaultVal) {
        return getValue(oldVal, String::toString, defaultVal);
    }

    public static Long getLongVal(String oldVal, Long defaultVal) {
        return getValue(oldVal, Long::valueOf, defaultVal);
    }

    /**
     * 从上下文缓存中获取用户ID，默认为0
     *
     * @return 用户ID
     */
    public static Long getUserId() {
        return getLongVal(get(BaseContextConstants.JWT_KEY_USER_ID), 0L);
    }

    /**
     * 设置用户ID
     *
     * @param userId 用户ID
     */
    public static void setUserId(Long userId) {
        set(BaseContextConstants.JWT_KEY_USER_ID, userId);
    }

    /**
     * 设置用户ID
     *
     * @param userId 用户ID
     */
    public static void setUserId(String userId) {
        setUserId(getLongVal(userId, 0L));
    }

    /**
     * 获取登录的账号
     *
     * @return 账号
     */
    public static String getAccount() {
        return getDefaultVal(get(BaseContextConstants.JWT_KEY_ACCOUNT), EMPTY);
    }

    /**
     * 设置账号键值对
     *
     * @param account 账号
     */
    public static void setAccount(String account) {
        set(BaseContextConstants.JWT_KEY_ACCOUNT, account);
    }

    /**
     * 获取用户名称
     *
     * @return 用户名称
     */
    public static String getName() {
        return getDefaultVal(BaseContextConstants.JWT_KEY_NAME, EMPTY);
    }

    /**
     * 设置用户名称
     *
     * @param name 用户名称
     */
    public static void setName(String name) {
        set(BaseContextConstants.JWT_KEY_NAME, name);
    }

    /**
     * 获取Token
     *
     * @return Token字符串
     */
    public static String getToken() {
        return getDefaultVal(get(BaseContextConstants.TOKEN), EMPTY);
    }

    /**
     * 设置Token
     *
     * @param token token字符串
     */
    public static void setToken(String token) {
        set(BaseContextConstants.TOKEN, token);
    }

    public static void setDatabase(String val) {
        set(BaseContextConstants.DATABASE_NAME, val);
    }

    public static void remove() {
        CACHE.remove();
    }

    public static Long getOrgId() {
        return NumberHelper.longValueOf0(get(BaseContextConstants.JWT_KEY_ORG_ID));
    }

    public static Long getPositionId() {
        return NumberHelper.longValueOf0(get(BaseContextConstants.JWT_KEY_POSITION_ID));
    }

    public static void setOrgId(String orgId) {
        set(BaseContextConstants.JWT_KEY_ORG_ID, orgId);
    }

    public static void setPositionId(String positionId) {
        set(BaseContextConstants.JWT_KEY_POSITION_ID, positionId);
    }
}
